#! /bin/bash
#
# makemake.sh    
#

declare -r IDE_PATH=$(pwd)

MANUAL="\
USAGE
  makemake.sh [-h] [<dir>] 

  -h    :   print this manual
  <dir> :   the directory in which the Makefile system is generated

  The script generates a working Makefile for the specified directory <dir>
  follwing the directives given in file OPTIONS.
  The OPTIONS file contains also the global definitions set in \${IDEHOME}/OPTIONS.
  The developer controls the Makefile generation editing OPTIONS.
  Unspecified field in OPTIONS would be assumed according to a 
  set default (loaded from file \${IDEHOME}/IDE/IDE.conf ).
  The script must be used in the \${IDEHOME} dir.  "

#
# input check
shopt -s extglob
shopt -s nullglob
if [ "$1" = "-h" ] ; then echo "$MANUAL" ; exit 0 ; fi
if [ "$#" != "1" ] ; then 
    echo " Invalid number of arguments, type makemake.sh -h for help" 
    exit 1
fi
#
# load DEFAULTS
if [ ! -e ./IDE/IDE.conf ] ; then
   echo "ERROR: Unable to find ./IDE/IDE.conf" ; exit 1
fi
source ./IDE/IDE.conf

directory=$1
if [[ $directory != $NAMERULE ]] ; then
    echo " Invalid name: $directory"
    exit 1
fi
if [ ! -d $directory ] ; then 
    echo " Input argument is not a directory, type makemake.sh -h for help" 
    exit 1
fi
if [[ ! -r $directory/README ]] ; then
    echo " File $directory/README is not present"
   exit 1
fi
uppercase_directory="$(echo "$directory" | tr "[a-z]" "[A-Z]")"
version="$(IDE/getoption VERSION < $directory/README)"
package="$(IDE/getoption PACKAGE < $directory/README)"
authors="$(IDE/getoption AUTHORS < $directory/README)"

if [[ $version != $VERSRULE ]] ; then
  echo " Version string does not fit the rules"
  exit 1
fi

#
# update DEFAULT dirs (as tmp) in $directory
if ! IDE/dir_setup.sh $directory ; then 
    echo "ERROR: in setting directories" ; exit 1
fi


#
# Manage Tmp dir
tmpdir=$directory/$STDDIR_TMP/$$
[ -e $tmpdir ] && rm -rf $tmpdir
mkdir $tmpdir
makefile=$tmpdir/Makefile.tmp
   
#
# set trap for clean exit in case of stopping
trap "test -d $tmpdir && rm -rf $tmpdir" EXIT

HEADER="$(cat << EOF
#
# DO NOT EDIT THIS FILE MANUALLY
# This makefile was automatically generated
# Directory : $directory
# Package   : $package
# Version   : $version
# Authors   : $authors
#
# Today is $(date)
#
EOF
)"

echo "$HEADER" > $makefile

#
# option file
options=
txt=
if test -r OPTIONS ; then
  options="$options$(cat OPTIONS)
"
  echo "# Global OPTIONS file has been used in generation" >> $makefile
else
  echo "# Global OPTIONS file has NOT been found" >> $makefile
fi
if test -r $directory/OPTIONS ; then
  options="$options$(cat $directory/OPTIONS)
"
  echo "# Local OPTIONS file has been used in generation" >> $makefile
else
  echo "# Local OPTIONS file has NOT been found" >> $makefile
fi

#
# versions
#
IDE/makeversion.sh $directory

#
# ORA ESEGUI I COMANDI IN BEFORE_MAKEMAKE
#
# setting DEFAULT for variables 
POSSIBLE_MAIN="@undef@"
ADD_TO_MAIN=
IDEHOME=../..
#
# cd-ing in the package home
cd $directory
#
eval "$(echo "$options" | ../IDE/getoption BEFORE_MAKEMAKE)"
# FINE COMANDI
# come back to IDE main dir
cd $IDE_PATH


#
# get sources
src=" $(cd $directory/$STDDIR_SOURCE ; echo $SUFFIXES_SOURCE) "
cat >> $makefile << EOF
#
# Sources defined by: $SUFFIXES_SOURCE
EOF

# no source
if test -z "$src"
then
cat >> $makefile << EOF
#
# There is no source file in this directory
EOF
fi


#
# if exist sources
if [ "$src" ] ; then

    #
    # define main programs

    # substitute defined macro
    #
    case "$POSSIBLE_MAIN" in
       @undef@)          src_for_main="$src"  ;;
       @NONE@|@none@)    src_for_main="" ;;
       *)                src_for_main="$POSSIBLE_MAIN" ;;
    esac

    #
    # add files assumed to be main
    test -z "$src_for_main" ||
       src_main="$(cd $directory/$STDDIR_SOURCE ; ../../IDE/check_main $src_for_main)"
    src_main="${ADD_TO_MAIN}${src_main}"

    #
    # define lib sources

    src_lib="$src"
    for file_main in $src_main ; do
        src_lib="${src_lib//" "$file_main" "/ }"
    done

    #
    # define objs from sources
    obj_main=""
    obj_lib=""
    for file in $src_main ; do
        obj_main="$obj_main ${file%.*}.o"
    done
    for file in $src_lib ; do
        obj_lib="$obj_lib ${file%.*}.o"
    done

    if test "$src_main"
    then
      echo "#"                                   >> $makefile
      echo "# List of MAIN source files"        >> $makefile
      echo "# (Fortran files containing a program statement):" >> $makefile
      echo "# $src_main" | IDE/split_line 80     >> $makefile
    fi
    if test "$src_lib"
    then
      echo "#"                                   >> $makefile
      echo "# List of LIB source files"         >> $makefile
      echo "# (Fortran files NOT containing a program statement and c files):" >> $makefile
      echo "# $src_lib" | IDE/split_line 80   >> $makefile
    fi
    echo "#"                                     >> $makefile

#
# METTI UN CONTROLLO SUI DOPPIONI PIU' VELOCE DI QUESTO
#    for file in $src ; do
#      for file2 in $src ; do
#        if [ $file != $file2 ] && [ ${file%.*} = ${file2%.*} ] ; then
#          echo "Duplicated source file: $file $file2" ; exit 1
#        fi
#      done
#    done
#

    used="$(IDE/used -s -d $directory)"
    linked=
    for dir in $directory $used ; do
      linked="$linked$(IDE/linked $dir) "
    done

    echo "# Used libraries"                        >> $makefile
    echo "#" $used | IDE/split_line 80             >> $makefile
    echo "#"                                       >> $makefile
    echo "# Linked libraries"                      >> $makefile
    echo "#" $linked | IDE/split_line 80           >> $makefile
    echo "#"                                       >> $makefile

    echo "# The real Makefile starts here"         >> $makefile
    echo "#"                                       >> $makefile

    echo "# IDE HOME variable set to DEFAULT"      >> $makefile
    echo "IDEHOME=$IDEHOME"                        >> $makefile
    echo "#"                                       >> $makefile

    echo "# Objects to be linked in the library"   >> $makefile
    echo "OBJ_LIB=$obj_lib" | IDE/split_line 80    >> $makefile
    echo                                           >> $makefile
LIBRARIES="$(cat << EOF
#

# Macros to link the present library
# (may be change by make.sys to the path of installed library)
LIB_${uppercase_directory}=lib${directory}.a
LIB_${uppercase_directory}_INCLUDE=-I. -I\$(IDEHOME)/$directory/$STDDIR_INCLUDE

# Switch to enable actual compilation
# (may be change by make.sys to "external")
LIB_${uppercase_directory}_SWITCH=internal
EOF
for file in $(IDE/reverse $used) ; do
  uppercase_file="$(echo "$file" | tr "[a-z]" "[A-Z]")"
cat << EOF
# Options to link the $uppercase_file library
LIB_${uppercase_file}=\$(IDEHOME)/$file/$STDDIR_SOURCE/lib${file}.a
LIB_${uppercase_file}_INCLUDE=-I\$(IDEHOME)/$file/$STDDIR_SOURCE/ \
  -I\$(IDEHOME)/$file/$STDDIR_INCLUDE

EOF

done
for file in $(IDE/reverse $linked) ; do
  uppercase_file="$(echo "$file" | tr "[a-z]" "[A-Z]")"
cat << EOF
# Options to link the $uppercase_file library
LIB_${uppercase_file}=
LIB_${uppercase_file}_INCLUDE=

EOF
done
    auto_include="\$(LIB_${uppercase_directory}_INCLUDE) "
    auto_libs="\$(LIB_${uppercase_directory}) "
    for file in $(IDE/reverse $used) $(IDE/reverse $linked)
    do
      uppercase_file="$(echo "$file" | tr "[a-z]" "[A-Z]")"
      auto_include="$auto_include\$(LIB_${uppercase_file}_INCLUDE) "
      auto_libs="$auto_libs\$(LIB_${uppercase_file}) "
    done
    #
echo "# Path for include"                        
echo "AUTO_INCLUDE=$auto_include" | IDE/split_line 80  
echo
echo "# List of used library files"              
echo "AUTO_LIBS=$auto_libs" | IDE/split_line 80  
)"
echo "$LIBRARIES" >> $makefile

libs="lib${directory}.a"
for file in $(IDE/reverse $used) ; do 
    libs="${libs} \$(IDEHOME)/$file/src/lib${file}.a" 
done

fi
#define the list of files to tar


# SYSTEM DEPENDENT FILES
INCLUDES="$(
    echo "# Inclusion of system dependent files"
    echo "include \$(IDEHOME)/make.sys"
    echo
)"
echo "$INCLUDES" >> $makefile

#
# definitions
# keyword DEFINITION from file OPTIONS
#
    txt="$(echo "$options" | IDE/getoption DEFINITION)"
    echo "# Macro (re)definitions from OPTIONS file (keyword DEFINITION)" >> $makefile
    if [ "$txt" ] ; then
       echo "$txt"                                      >> $makefile
    else
       echo "# Nothing found" >> $makefile
    fi
     echo                                             >> $makefile
    

#
# objs target definition
#
cat >> $makefile << EOF
# Main target
# INFO print a short help
info:
	@make print_info
EOF


#
# objs target definition
#
    echo "# INFO make local library and all executables" >> $makefile
    echo "all:"                            >> $makefile
    echo "	make loclib"               >> $makefile
    for file in $obj_main
    do
      echo "	make ${file%.o}.x"  >> $makefile
    done
    echo                                   >> $makefile
    echo "# INFO make local library" >> $makefile
    echo "loclib: libs loclib_only"         >> $makefile
    echo                                   >> $makefile
    echo "loclib_only: ide_\$(LIB_${uppercase_directory}_SWITCH)" >> $makefile
    echo >> $makefile
    echo "ide_internal: lib${directory}.a"              >> $makefile
    echo >> $makefile
    echo "ide_external: fake_external.a" >> $makefile
    echo >> $makefile
    echo "fake_external.a:" >> $makefile
    echo "	touch \$(OBJ_LIB)"     >> $makefile
    echo "	touch lib${directory}.a" >> $makefile
    echo "	touch fake_external.a" >> $makefile

#
# executables loading 
#
    echo "# Targets for executables"       >> $makefile
    for file in $obj_main
    do
      echo "# INFO make program ${file%.o}.x" >> $makefile
      echo "${file%.o}.x: ${file} $libs"  >> $makefile
      echo "	make loclib_only" >> $makefile
      echo "	\$(LD) \$(LDFLAGS) -o ${file%.o}.x $file \$(LIBOBJS) \$(LIBS)" >> $makefile
      echo "	cd \$(IDEHOME)/$directory/$STDDIR_BINARY ; \
  ln -sf \$(IDEHOME)/$directory/$STDDIR_SOURCE/${file%.o}.x . " >> $makefile
    done
    echo                                          >> $makefile
    echo                                          >> $makefile
    

#
# local library
#
    echo "# Targets for libraries"                >> $makefile
    echo "# INFO make local library (without the used libraries)" >> $makefile
    echo "lib${directory}.a: \$(OBJ_LIB)"                       >> $makefile
    echo "	\$(AR) \$(ARFLAGS) lib${directory}.a \$(OBJ_LIB)"    >> $makefile
    echo "	\$(RANLIB) lib${directory}.a"                        >> $makefile
    echo                                                             >> $makefile

#
# other libraries
#
    echo "# INFO make all the used libs" >> $makefile
    echo "libs:"                                  >> $makefile
    for file in $used
    do
      echo "	cd \$(IDEHOME)/$file/$STDDIR_SOURCE ; make loclib_only"   >> $makefile
    done
    echo                                          >> $makefile
    echo                                          >> $makefile

    
#
# Makefile re-generation
#
echo "# target for making Makefile"                 >> $makefile
echo "# INFO make local Makefile"                   >> $makefile
echo "make: "                                       >> $makefile
echo "	cd \$(IDEHOME) ; IDE/makemake.sh $directory "    >> $makefile
echo                                                >> $makefile
echo "# INFO make local and libs Makefiles"         >> $makefile
echo "allmake:"                                     >> $makefile
for lib in $used
do
    echo "	cd \$(IDEHOME) ; IDE/makemake.sh $lib "  >> $makefile
done
echo "	cd \$(IDEHOME) ; IDE/makemake.sh $directory " >> $makefile
echo                                                >> $makefile
echo                                                >> $makefile

#
# cleaning
#
echo "# target for cleaning"                        >> $makefile
echo "clean_: clean"                                >> $makefile
echo "# INFO cleanup"                               >> $makefile
echo "clean: "                                      >> $makefile
echo "	- rm -f $SUFFIXES_CLEAN"                    >> $makefile
echo '	if test -d ' "\$(IDEHOME)/$directory/$STDDIR_TMP/CVS " '; then \' >> $makefile
echo '	mv ' "\$(IDEHOME)/$directory/$STDDIR_TMP/CVS" '\'   >> $makefile
echo "	\$(IDEHOME)/$directory/$STDDIR_TMP/.CVS ; fi"       >> $makefile
echo "	- rm -rf \$(IDEHOME)/$directory/$STDDIR_TMP/*"      >> $makefile
echo '	if test -d ' "\$(IDEHOME)/$directory/$STDDIR_TMP/.CVS " '; then \' >> $makefile
echo '	mv ' "\$(IDEHOME)/$directory/$STDDIR_TMP/.CVS "' \' >> $makefile 
echo "	\$(IDEHOME)/$directory/$STDDIR_TMP/CVS ; fi"        >> $makefile
echo "	- rm -f \$(IDEHOME)/$directory/$STDDIR_BINARY/*.x " >> $makefile
echo                                                >> $makefile

#
# tarlist (this is a special target, only in the inner file)
#
echo "tarlist: "                                    >> $makefile
echo "	cd \$(IDEHOME) ; IDE/tarlist.sh $directory > $directory/tmp/tarlist" >> $makefile
echo >> $makefile


echo "# INFO gzipped tar" >> $makefile
echo "tar: tarlist" >> $makefile
echo "	cd \$(IDEHOME) ; \
        tar cf $directory-$version.tar \`cat $directory/tmp/tarlist\`" >> $makefile
echo "	cd \$(IDEHOME) ; gzip -9 $directory-$version.tar" >> $makefile
echo >> $makefile

echo "# INFO gzipped tar including used libraries and IDE" >> $makefile
echo "alltar: " >> $makefile
echo "	cd \$(IDEHOME) ; \
        tar cf $directory-$version-withdeps.tar IDE CONFIG configure Makefile" >> $makefile
test -r OPTIONS &&
  echo "	cd \$(IDEHOME) ; \
        tar rf $directory-$version-withdeps.tar OPTIONS" >> $makefile
echo "	cd \$(IDEHOME) ;  \
        tar rf $directory-$version-withdeps.tar \`cat $directory/tmp/tarlist\`" >> $makefile
for lib in $used ; do
  echo "	cd \$(IDEHOME)/$lib/src ; make tarlist" >> $makefile
  echo "	cd \$(IDEHOME) ; tar rf $directory-$version-withdeps.tar \`cat $lib/tmp/tarlist\`" >> $makefile
done
echo "	cd \$(IDEHOME) ; gzip -9 $directory-$version-withdeps.tar" >> $makefile
echo >> $makefile

#
# directly added Makefile lines
# keyword MAKEFILE in OPTIONS
# 
# see later on keyword HOME_MAKEFILE for
# lines directly added to outer Makefile
#
    echo "# Directly added lines from OPTIONS file (keyword MAKEFILE)" >> $makefile
    txt=`echo "$options" | IDE/getoption MAKEFILE`
    if [ ! -z "$txt" ] ; then
       echo "# Directly added lines"                >> $makefile
       echo "$txt"                                  >> $makefile
       echo                                         >> $makefile
    else
       echo "# Nothing found" >> $makefile
    fi

             


#
# Makefile special rules
#
     echo "# Special rules for selected files (keyword DEFINITION.filebase)" >> $makefile
found="$(echo "$options" | IDE/getoption "DEFINITION.*")"
if [ "$found" ] ; then
    first=yes 
    for file in $src
    do
        file_base="${file%.*}"
        newrule="$(echo "$options" | IDE/getoption DEFINITION.$file_base)"
        #
        # if something is found
        if [ "$newrule" ] ; then
# Temporaneamente, lo faccio copiando il file makefile
# Ci sarebbero varie cose inutili, e da eliminare
             makefile_name=$tmpdir/Makefile.$file_base
             echo "$HEADER"                             > $makefile_name
             echo "# Special makefile for file $file"  >> $makefile_name
             echo "IDEHOME=$IDEHOME"                   >> $makefile_name
             echo "$LIBRARIES"                         >> $makefile_name
             echo                                      >> $makefile_name
             echo "$INCLUDES"                          >> $makefile_name
             echo                                      >> $makefile_name
             echo "$newrule"                           >> $makefile_name

             if [ "$first" ] ; then 
                echo "# Special rules"                 >> $makefile
                first=
             fi
             echo "$file_base.o: $file"                >> $makefile
             echo "	make -f Makefile.$file_base $file_base.o"  >> $makefile
             echo                                      >> $makefile
        fi
    done
    echo                                         >> $makefile
else
    echo "# Nothing found" >> $makefile
fi
    echo >> $makefile

cat >> $makefile << EOF
print_info:
	@echo " Package : $package"
	@echo " Version : $version"
	@echo " Authors : $authors"
	@echo
	@echo " type:  make <target>"
	@echo " Possible <target>'s are:"
EOF
cat $makefile | IDE/makeinfo.sh >> $makefile

if [ "$src" ] ; then
    #
    echo "# Dependencies"                           >> $makefile
    cd $directory/$STDDIR_SOURCE
        dirs="../$STDDIR_INCLUDE"
        for lib in $used ; do
            dirs="$dirs ../../$lib/$STDDIR_SOURCE ../../$lib/$STDDIR_INCLUDE"
        done
        # 
        # search for dependencies
        txt=`../../IDE/moduledep.sh $dirs` 
    cd -           
    # check for missing dependencies
    txttmp=`echo "$txt" | grep @`
    if [ -n "$txttmp" ] ; then 
        echo "$txttmp"
        echo "WARNING: modules not found in directories:"
        echo "         $dirs"
    fi
    echo "$txt"                                     >> $makefile
    echo "# End dependencies"                       >> $makefile
fi

#
# Outer makefile generation
#for target in $list_of_targets
#do
  #echo                                               >> $makefile_outer
  #echo "$target: "                                   >> $makefile_outer
  #echo "	cd $STDDIR_SOURCE ; make $target "   >> $makefile_outer
#done
#
##
## directly added Makefile lines in outer Makefile
## keyword HOME_MAKEFILE in OPTIONS
## 
  #echo                                               >> $makefile_outer
  #txt=`echo "$options" | IDE/getoption HOME_MAKEFILE`
  #if [ ! -z "$txt" ] ; then
     #echo "# Directly added lines"                   >> $makefile_outer
     #echo "$txt"                                     >> $makefile_outer
     #echo                                            >> $makefile_outer
  #fi
#
##
# now copy the created makefile in the right positions
rm -f  $directory/$STDDIR_SOURCE/Makefile  $directory/$STDDIR_SOURCE/Makefile.*
mv $makefile $directory/$STDDIR_SOURCE/Makefile
[ "$(echo $tmpdir/Makefile.*)" ] && cp $tmpdir/Makefile.* $directory/$STDDIR_SOURCE
IDE/makeouter.sh $STDDIR_SOURCE < $directory/$STDDIR_SOURCE/Makefile > $directory/Makefile

exit 0

